package com.mimosa.common.system.menu;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

import javax.annotation.PostConstruct;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mimosa.common.dao.HibernateDao;
import com.mimosa.common.service.CommonService;
import com.mimosa.util.config.YesNoType;

/**
 * 菜单信息的业务类
 * 
 * @filename MenuItemService.java
 * @date 2012-3-2 下午6:19:23
 * @author ggeagle
 * 
 */
@Service
@Transactional
public class MenuItemService extends CommonService<TMenuItem, String> {
	/**
	 * 菜单的分隔符
	 */
	@Autowired
	private TMenuItemDao menuItemDao;

	private Map<String, String> pathToMap = null;
	private Map<String, TMenuItem> menuContext = null;

	public MenuItemService() {
		this.pathToMap = new HashMap<String, String>();
		this.menuContext = new TreeMap<String, TMenuItem>(new Comparator<String>() {
			public int compare(String o1, String o2) {
				return o1.compareTo(o2);
			}
		});
	}

	public List<TMenuItem> needGrantMenu() {
		return this.menuItemDao.findBy("needGrant", YesNoType.Y.name());
	}

	/**
	 * 初始化菜单及访问路径信息到内存中，加快程序访问速度
	 */
	@PostConstruct
	public void initMenuList() {
		this.pathToMap.clear();
		this.menuContext.clear();
		List<TMenuItem> itemList = this.menuItemDao.getAll("menuCode", true);
		for (TMenuItem menuItem : itemList) {
			this.menuContext.put(menuItem.getId(), menuItem);
			this.pathToMap.put(menuItem.getMenuUrl(), menuItem.getId());
		}
	}

	/**
	 * 根据访问路径获取当前访问的菜单信息
	 * 
	 * @param urlPath
	 * @return
	 */
	public TMenuItem getVisitMenuItem(String urlPath) {
		if (this.menuContext.size() < 1) {
			this.initMenuList();
		}
		if (StringUtils.startsWith(urlPath, "/")) {
			urlPath = urlPath.substring(1);
		}
		String menuId = this.pathToMap.get(urlPath);
		TMenuItem menuItem = null;
		if (StringUtils.isNotBlank(menuId)) {
			menuItem = this.menuContext.get(menuId);
		}
		return menuItem;
	}

	/**
	 * 删除菜单实体对象
	 * 
	 * @param menuItem
	 *            菜单对象
	 */
	public void deleteEntity(TMenuItem menuItem) {
		this.menuItemDao.delete(menuItem);
	}

	/**
	 * 获取全部的菜单信息对象列表
	 * 
	 * @return
	 */
	public List<TMenuItem> getAll() {
		return this.menuItemDao.getAll();
	}

	/**
	 * 批量保存菜单对象信息
	 * 
	 * @param menuItemList
	 *            菜单对象列表
	 */
	public void saveEntityList(List<TMenuItem> menuItemList) {
		if (menuItemList != null) {
			for (TMenuItem menuItem : menuItemList) {
				if (StringUtils.isBlank(menuItem.getId())) {
					menuItem.setId(UUID.randomUUID().toString().replace("-", ""));
				}
				this.menuItemDao.save(menuItem);
			}
		}
	}

	/**
	 * 根据角色id获取该角色不关联的菜单
	 * 
	 * @param id
	 *            角色id
	 * @return
	 */
	public List<TMenuItem> selWMenuByRoleId(String id) {
		return this.menuItemDao.find(
				"from TMenuItem m where m.id not in (select distinct(r.itemId) from TPermission r where r.roleOrUserId = ?)",
				id);
	}

	/**
	 * 根据角色id获取该角色有权限的菜单
	 * 
	 * @param id
	 * @return
	 */
	public List<TMenuItem> selYMenuByRoleId(String id) {
		return this.menuItemDao.find(
				"from TMenuItem m where m.id in (select distinct(r.itemId) from TPermission r where r.roleOrUserId = ?)",
				id);
	}

	/**
	 * 除去parentId = 0的数据
	 * 
	 * @return
	 */
	public List<TMenuItem> getAllbypId() {
		return this.menuItemDao.find("from TMenuItem m where m.needGrant=?", YesNoType.Y.name());
	}

	/**
	 * 根据菜单的主键获取对应的菜单信息对象
	 * 
	 * @param id
	 *            菜单信息主键
	 * @return
	 */
	public TMenuItem getEntity(String id) {
		return this.menuContext.get(id);
	}

	/**
	 * 获取菜单的子菜单列表
	 * 
	 * @param parentId
	 *            子菜单的父ID
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<TMenuItem> getChildren(final String menuCode) {
		return (List<TMenuItem>) CollectionUtils.select(this.menuContext.values(), new Predicate() {
			public boolean evaluate(Object object) {
				TMenuItem item = (TMenuItem) object;

				return item.getMenuCode().startsWith(menuCode)
						&& (item.getMenuCode().length() == menuCode.length() + MenuItemHelper.ID_LENGTH);
			}
		});
	}

	@Override
	protected HibernateDao<TMenuItem, String> getHibernateDao() {
		return this.menuItemDao;
	}
}